// Released in the Public Domain. http://creativecommons.org/licenses/publicdomain/
package org.xi8ix.async.spi;

import org.xi8ix.async.AsyncEngine;
import org.xi8ix.async.Peer;
import org.xi8ix.async.Receiver;
import org.xi8ix.async.Server;

import java.io.IOException;
import java.net.InetSocketAddress;

/**
 * A simple factory of Async implementation objects. Helps to separate package local implementation objects
 * from the core API.
 *
 * @author Iain Shigeoka
 */
public class AsyncProvider {
    /** The engine that will drive provided objects. */
    private AsyncEngine engine;

    /**
     * Create a provider that will use the provided engine for configuration.
     *
     * @param engine the engine provider objects will use
     */
    public AsyncProvider(AsyncEngine engine) {
        this.engine = engine;
    }

    /**
     * Create a datagram (UDP) server that binds to a local address and waits for incoming data (which
     * generates peers).
     *
     * @param localAddress the local address to bind the socket to
     * @param receiver receives incoming data
     * @return the server
     * @throws IOException if there was a problem creating the server
     */
    public Server createDatagramServer(InetSocketAddress localAddress, Receiver receiver) throws IOException {
        return new DatagramServer(localAddress, receiver, engine);
    }

    /**
     * Create a socket (TCP) server that binds to a local address and waits for incoming connections (which
     * generates peers).
     *
     * @param localAddress the local address to bind the socket to
     * @param receiver receives incoming data
     * @return the server
     * @throws IOException if there was a problem creating the server
     */
    public Server createSocketServer(InetSocketAddress localAddress, Receiver receiver) throws IOException {
        return new SocketServer(localAddress, receiver, engine);
    }

    /**
     * Create a socket peer (client TCP socket) that binds to a particular local address and connects to
     * the given remote remote address.
     *
     * @param localAddress the local address to bind the socket to or null to use an ephemeral local address
     * @param remoteAddress the remote address to connect the socket to
     * @param receiver receives incoming data
     * @return the peer
     * @throws IOException if there was a problem creating the peer
     */
    public Peer createSocketPeer(InetSocketAddress localAddress, InetSocketAddress remoteAddress, Receiver receiver) throws IOException {
        return new SocketPeer(localAddress, remoteAddress, receiver, engine);
    }
}
